#include <iostream>
#include <string>
#include <unistd.h>
#include "task.hpp"
// #include "queue_v1.hpp"
// #include "queue_v2.hpp"
// #include "loop_queue_v1.hpp"
#include "loop_queue_v2.hpp"

// typedef block_queue<task> queue;
typedef loop_queue<task> queue;

const size_t th_num = 5;
const std::string ops = "+-*/%";

void* producer(void* args)
{
    queue* bq = static_cast<queue*>(args);

    while (true)
    {
        int x = rand() % 10;
        int y = rand() % 10;
        char op = ops[rand() % ops.size()];

        task t(x, y, op);
        t.print_expression();
        bq->push(t);
    }
    return nullptr;
}

void* consumer(void* args)
{
    queue* bq = static_cast<queue*>(args);

    while (true)
    {
        task t;
        bq->pop(&t);
        t();
        t.print_result();
    }
    return nullptr;
}

int main()
{
    srand(time(0) ^ getpid());
    queue* bq = new queue;

    pthread_t p[th_num], c[th_num];
    for (int i = 0; i < th_num; i++)
    {
        pthread_create(&p[i], nullptr, producer, bq);
        pthread_create(&c[i], nullptr, consumer, bq);
    }

    for (int i = 0; i < th_num; i++)
    {
        pthread_join(p[i], nullptr);
        pthread_join(c[i], nullptr);
    }

    delete bq;
    return 0;
}
